package xxl.signals.base.natives 
{
	import flash.events.Event;
	import flash.events.IEventDispatcher;
	import xxl.signals.base.PrioritySignal;
	import xxl.signals.base.Slot;
	import xxl.signals.core.ISlot;
	import xxl.signals.core.natives.INativeDispatcher;
	
	/**
	 * ...
	 * @author XXL
	 */
	public class NativeRelaySignal extends PrioritySignal implements INativeDispatcher 
	{
		protected var _target:IEventDispatcher;
		protected var _eventType:String;
		protected var _eventClass:Class;
		protected var _useCapture:Boolean;
		
		public function NativeRelaySignal(target:IEventDispatcher = null, eventType:String = "", eventClass:Class = null, useCapture:Boolean = false) 
		{
			super(eventClass || Event);
			
			this.target = target;
			_eventType = eventType;
			_eventClass = eventClass || Event;
			_valueClasses = [_eventClass];
			_useCapture = useCapture;
		}
		
		override public function set valueClasses(value:Array):void 
		{
			var valueClass:Class = null;
			if (value && value.length > 0)
			{
				valueClass = value[0] as Class;
			}
			_eventClass = valueClass || Event;
			_valueClasses = [_eventClass];
		}
		
		override protected function registerListenerWithPriority(listener:Function, once:Boolean = false, priority:int = 0):ISlot
		{
			if (!target)
			{
				throw new ArgumentError("target为空");
			}
			const empty:Boolean = slots.length == 0;
			const slot:ISlot = super.registerListenerWithPriority(listener, once, priority);
			if (empty)
			{
				target.addEventListener(eventType, onNativeEvent, _useCapture);
			}
			return slot;
		}
		
		override public function remove(listener:Function):ISlot 
		{
			const slot:ISlot = super.remove(listener);
			if (slot && slots.length == 0)
			{
				target.removeEventListener(eventType, onNativeEvent, _useCapture);
			}
			return slot;
		}
		
		override public function removeAll():void 
		{
			if (target)
			{
				target.removeEventListener(eventType, onNativeEvent, _useCapture);
			}
			super.removeAll();
		}
		
		override public function dispatch(...valueObjects):void 
		{
			if (valueObjects == null)
			{
				throw new ArgumentError("缺少event");
			}
			if (valueObjects.length != 1)
			{
				throw new ArgumentError("只能传递一个为event的参数");
			}
			
			dispatchEvent(valueObjects[0] as Event);
		}
		
		protected function onNativeEvent(e:Event):void 
		{
			if (sortFlag)
			{
				sortFlag = false;
				slots = slots.sortOn("priority", Array.NUMERIC);
			}
			for (var i:int = slots.length; i--; )
			{
				slots[i].execute1(e);
			}
		}
		
		/* INTERFACE xxl.signals.core.natives.INativeDispatcher */
		
		public function get eventType():String 
		{
			return _eventType;
		}
		
		public function get eventClass():Class 
		{
			return _eventClass;
		}
		
		public function get target():IEventDispatcher 
		{
			return _target;
		}
		
		public function set target(value:IEventDispatcher):void 
		{
			if (value == _target)
			{
				return;
			}
			if (_target)
			{
				removeAll();
			}
			_target = value;
		}
		
		public function dispatchEvent(event:Event):Boolean 
		{
			if (!target)
			{
				throw new ArgumentError("target为空");
			}
			if (!event)
			{
				throw new ArgumentError("event为空");
			}
			if (!(event is eventClass))
			{
				throw new ArgumentError("event " + event + " 不是 " + eventClass);
			}
			if (event.type != eventType)
			{
				throw new ArgumentError("event type " + event.type + " 不是 " + eventType);
			}
			return target.dispatchEvent(event);
		}
		
		public function get useCapture():Boolean 
		{
			return _useCapture;
		}
		
	}

}